﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Security;
using System.Text;
using ThomasGIS.BaseConfiguration;
using ThomasGIS.Coordinates;
using ThomasGIS.Geometries;
using ThomasGIS.Helpers;
using ThomasGIS.Vector;
using ThomasGIS.SpatialIndex;
using System.Diagnostics;

namespace ThomasGIS.Network
{
    public class GeoNetwork : Network, IGeoNetwork
    {
        public readonly CoordinateBase networkCoordinateSystem;

        protected ISpatialIndex pointSpatialIndex;

        public GeoNetwork(CoordinateBase coordinateSystem) : base()
        {
            this.networkCoordinateSystem = coordinateSystem;
        }

        public GeoNetwork(IShapefile shapefile)
        {
            this.networkCoordinateSystem = shapefile.GetCoordinateRef();

            HashSet<string> pointSet = new HashSet<string>();

            // 从shapefile里拿到所有的道路节点构建顶点集合V
            for (int i = 0; i < shapefile.GetFeatureNumber(); i++)
            {
                Polyline polyline = shapefile.GetFeature(i) as Polyline;

                for (int j = 0; j < polyline.PartNumber; j++)
                {
                    int startLoc = polyline.PartList[j];
                    int endLoc;
                    if (j == polyline.PartNumber - 1)
                    {
                        endLoc = polyline.PointNumber;
                    }
                    else
                    {
                        endLoc = polyline.PartList[j + 1];
                    }

                    for (int k = startLoc; k < endLoc; k++)
                    {
                        pointSet.Add($"{ polyline.PointList[k].X },{ polyline.PointList[k].Y }");
                    }
                }
            }

            List<string> pointStrList = pointSet.ToList();
            pointSet.Clear();

            BoundaryBox mbr = shapefile.GetBoundaryBox();
            double scale = (mbr.XMax - mbr.XMin) / 1000.0;
            pointSpatialIndex = new GridSpatialIndex(mbr, scale);

            // 向网络中添加节点
            foreach (string pointString in pointStrList)
            {
                string[] coordinate = pointString.Split(',');
                double x = Convert.ToDouble(coordinate[0]);
                double y = Convert.ToDouble(coordinate[1]);
                GeoNetworkNode newNode = new GeoNetworkNode(this.NodeNumber, x, y, null);
                this.AddNode(newNode);
                pointSpatialIndex.AddItem(newNode);
            }

            pointSpatialIndex.RefreshIndex();

            // 构建点与边的关系
            for (int i = 0; i < shapefile.GetFeatureNumber(); i++)
            {
                Polyline polyline = shapefile.GetFeature(i) as Polyline;

                for (int j = 0; j < polyline.PartNumber; j++)
                {
                    int startLoc = polyline.PartList[j];
                    int endLoc;
                    if (j == polyline.PartNumber - 1)
                    {
                        endLoc = polyline.PointNumber;
                    }
                    else
                    {
                        endLoc = polyline.PartList[j + 1];
                    }

                    for (int k = startLoc; k < endLoc - 1; k++)
                    {
                        Point startPoint = polyline.PointList[k];
                        Point endPoint = polyline.PointList[k + 1];

                        IEnumerable<int> startNodeCandicateIndex = pointSpatialIndex.SearchID(startPoint, scale);
                        IEnumerable<int> endNodeCandicateIndex = pointSpatialIndex.SearchID(endPoint, scale);

                        GeoNetworkNode startNode = null, endNode = null;

                        foreach (int index in startNodeCandicateIndex)
                        {
                            GeoNetworkNode checkNode = this.NodeList[index] as GeoNetworkNode;
                            if (checkNode.X == startPoint.X && checkNode.Y == startPoint.Y)
                            {
                                startNode = checkNode;
                                break;
                            }
                        }

                        foreach (int index in endNodeCandicateIndex)
                        {
                            GeoNetworkNode checkNode = this.NodeList[index] as GeoNetworkNode;
                            if (checkNode.X == endPoint.X && checkNode.Y == endPoint.Y)
                            {
                                endNode = checkNode;
                                break;
                            }
                        }

                        if (startNode == null || endNode == null) throw new Exception("Big Error!");

                        Dictionary<string, object> dataField = new Dictionary<string, object>();
                        dataField.Add("SegmentID", i);

                        this.AddArc(new GeoNetworkArc(startNode, endNode, dataField));
                    }
                }
            }
        }

        public int GetArcNumber()
        {
            return this.ArcList.Count;
        }

        public int GetNodeNumber()
        {
            return this.NodeList.Count;
        }

        public override bool AddNode(INetworkNode newNode)
        {
            if (newNode.GetType() != typeof(GeoNetworkNode))
            {
                throw new Exception("只能在L4级网络中添加地理节点，请使用GeoNetworkNode类生成！");
            }

            this.NodeList.Add(newNode);

            return true;
        }

        public override bool AddNodes(IEnumerable<INetworkNode> nodeList)
        {
            foreach (INetworkNode node in nodeList)
            {
                AddNode(node);
            }

            return true;
        }

        public override bool AddArc(INetworkArc newArc)
        {
            if (newArc.GetType() != typeof(GeoNetworkArc))
            {
                throw new Exception("只能在L4级网络中添加地理节点，请使用GeoNetworkNode类生成！");
            }

            this.ArcList.Add(newArc);

            return true;
        }

        public override bool AddArcs(IEnumerable<INetworkArc> arcList)
        {
            foreach (INetworkArc arc in arcList)
            {
                AddArc(arc);
            }

            return true;
        }

        protected bool RefreshGridSpatialIndex()
        {
            double xmin = double.MaxValue, xmax = double.MinValue, ymin = double.MaxValue, ymax = double.MinValue;

            foreach (GeoNetworkNode oneNode in this.NodeList)
            {
                xmin = oneNode.GetX() < xmin ? oneNode.GetX() : xmin;
                xmax = oneNode.GetX() > xmax ? oneNode.GetX() : xmax;
                ymin = oneNode.GetY() < ymin ? oneNode.GetY() : ymin;
                ymax = oneNode.GetY() > ymax ? oneNode.GetY() : ymax;
            }

            double scale = (xmax - xmin) / 1000.0;
            pointSpatialIndex = new GridSpatialIndex(new BoundaryBox(xmin, ymin, xmax, ymax), scale);

            foreach (GeoNetworkNode oneNode in this.NodeList)
            {
                pointSpatialIndex.AddItem(oneNode);
            }

            pointSpatialIndex.RefreshIndex();

            return true;
        }

        public override void RefreshNeighborMatrix(string dataField = null)
        {
            if (dataField == null)
            {
                dataField = nowMatrixField;
            }

            RefreshGridSpatialIndex();

            // 有多少个点就有多少条记录，记录内的长度不一致
            this.neighborMatrix = new List<List<LinkValuePair>>();
            // 由于邻接矩阵空间占用较大，在放弃前一个矩阵后应当执行GC过程释放内存
            GC.Collect();
            for (int i = 0; i < NodeNumber; i++)
            {
                this.neighborMatrix.Add(new List<LinkValuePair>());
            }

            for (int i = 0; i < this.ArcList.Count; i++)
            {
                GeoNetworkArc oneArc = this.ArcList[i] as GeoNetworkArc;

                IEnumerable<int> startNodeCandicateIndex = pointSpatialIndex.SearchID(new Point(oneArc.StartPoint.X, oneArc.StartPoint.Y), this.pointSpatialIndex.GetScale());
                IEnumerable<int> endNodeCandicateIndex = pointSpatialIndex.SearchID(new Point(oneArc.EndPoint.X, oneArc.EndPoint.Y), this.pointSpatialIndex.GetScale());

                int startNodeIndex = -1, endNodeIndex = -1;

                foreach (int index in startNodeCandicateIndex)
                {
                    GeoNetworkNode checkNode = this.NodeList[index] as GeoNetworkNode;
                    if (checkNode.X == oneArc.StartPoint.X && checkNode.Y == oneArc.StartPoint.Y)
                    {
                        startNodeIndex = index;
                        break;
                    }
                }

                foreach (int index in endNodeCandicateIndex)
                {
                    GeoNetworkNode checkNode = this.NodeList[index] as GeoNetworkNode;
                    if (checkNode.X == oneArc.EndPoint.X && checkNode.Y == oneArc.EndPoint.Y)
                    {
                        endNodeIndex = index;
                        break;
                    }
                }

                if (startNodeIndex == -1 || endNodeIndex == -1) throw new Exception("Big Error!");

                if (dataField != "")
                {
                    // 如果边的属性表中不包含该字段，则直接跳过
                    if (!oneArc.GetKeys().Contains(dataField)) continue;

                    this.neighborMatrix[startNodeIndex].Add(new LinkValuePair(endNodeIndex, (double)oneArc.GetProperty(dataField), i));
                    this.neighborMatrix[endNodeIndex].Add(new LinkValuePair(startNodeIndex, (double)oneArc.GetProperty(dataField), i));
                }
                else
                {
                    double distance;
                    if (networkCoordinateSystem.GetCoordinateType() == CoordinateType.Projected)
                    {
                        distance = DistanceCalculator.SpatialDistance(oneArc.StartPoint, oneArc.EndPoint);
                    }
                    else
                    {
                        distance = DistanceCalculator.SpatialDistanceGeo(oneArc.StartPoint, oneArc.EndPoint);
                    }
                    this.neighborMatrix[startNodeIndex].Add(new LinkValuePair(endNodeIndex, distance, i));
                    this.neighborMatrix[endNodeIndex].Add(new LinkValuePair(startNodeIndex, distance, i));
                }
            }

            this.nowMatrixField = dataField;
            this.networkChangeFlag = false;
        }

        public IShapefile ExportNodesToShapefile()
        {
            // 识别所有弧段中的属性
            HashSet<KeyValuePair<string, DBFFieldType>> fieldSet = new HashSet<KeyValuePair<string, DBFFieldType>>();

            for (int i = 0; i < NodeNumber; i++)
            {
                GeoNetworkNode oneNode = this.NodeList[i] as GeoNetworkNode;
                foreach (string key in oneNode.GetKeys())
                {
                    object value = oneNode.GetProperty(key);
                    if (value.GetType() == typeof(int) || value.GetType() == typeof(double))
                    {
                        fieldSet.Add(new KeyValuePair<string, DBFFieldType>(key, DBFFieldType.Number));
                    }
                    else if (value.GetType() == typeof(string))
                    {
                        fieldSet.Add(new KeyValuePair<string, DBFFieldType>(key, DBFFieldType.Char));
                    }
                    else
                    {
                        fieldSet.Add(new KeyValuePair<string, DBFFieldType>(key, DBFFieldType.Binary));
                    }
                }
            }

            // 新建一个Shapefile
            IShapefile nodeShapefile = VectorFactory.CreateShapefile(ESRIShapeType.Point);

            // 新建Shapefile的属性表
            foreach (KeyValuePair<string, DBFFieldType> newFieldPair in fieldSet)
            {
                int length;
                int precision;

                if (newFieldPair.Value == DBFFieldType.Char)
                {
                    length = Convert.ToInt32(Configuration.GetConfiguration("geonetwork.property.string.length"));
                    precision = 0;
                }
                else if (newFieldPair.Value == DBFFieldType.Number)
                {
                    length = Convert.ToInt32(Configuration.GetConfiguration("geonetwork.property.numberic.length"));
                    precision = Convert.ToInt32(Configuration.GetConfiguration("geonetwork.property.numberic.precision"));
                }
                else
                {
                    length = Convert.ToInt32(Configuration.GetConfiguration("geonetwork.property.default.length"));
                    precision = 0;
                }

                nodeShapefile.AddField(newFieldPair.Key, newFieldPair.Value, length, precision);
            }

            nodeShapefile.AddField("ID", DBFFieldType.Number, 10, 0);

            // 插入节点与节点的属性表
            for (int i = 0; i < NodeNumber; i++)
            {
                GeoNetworkNode oneNode = this.NodeList[i] as GeoNetworkNode;
                oneNode.SetProperty("ID", oneNode.GetID());
                nodeShapefile.AddFeature(oneNode.TransferToPoint(), oneNode.GetPropertySheet());
            }

            // 设置shapefile的坐标系统
            nodeShapefile.SetCoordinateRef(this.networkCoordinateSystem);

            return nodeShapefile;
        }

        public IShapefile ExportArcsToShapefile()
        {
            // 识别所有弧段中的属性
            HashSet<KeyValuePair<string, DBFFieldType>> fieldSet = new HashSet<KeyValuePair<string, DBFFieldType>>();

            for (int i = 0; i < ArcNumber; i++)
            {
                INetworkArc oneArc = this.ArcList[i];
                foreach (string key in oneArc.GetKeys())
                {
                    object value = oneArc.GetProperty(key);
                    if (value.GetType() == typeof(int) || value.GetType() == typeof(double))
                    {
                        fieldSet.Add(new KeyValuePair<string, DBFFieldType>(key, DBFFieldType.Number));
                    }
                    else if (value.GetType() == typeof(string))
                    {
                        fieldSet.Add(new KeyValuePair<string, DBFFieldType>(key, DBFFieldType.Char));
                    }
                    else
                    {
                        fieldSet.Add(new KeyValuePair<string, DBFFieldType>(key, DBFFieldType.Binary));
                    }
                }
            }

            // 新建一个Shapefile
            IShapefile nodeShapefile = VectorFactory.CreateShapefile(ESRIShapeType.Polyline);

            // 新建Shapefile的属性表
            foreach (KeyValuePair<string, DBFFieldType> newFieldPair in fieldSet)
            {
                int length;
                int precision;

                if (newFieldPair.Value == DBFFieldType.Char)
                {
                    length = Convert.ToInt32(Configuration.GetConfiguration("geonetwork.property.string.length"));
                    precision = 0;
                }
                else if (newFieldPair.Value == DBFFieldType.Number)
                {
                    length = Convert.ToInt32(Configuration.GetConfiguration("geonetwork.property.numberic.length"));
                    precision = Convert.ToInt32(Configuration.GetConfiguration("geonetwork.property.numberic.precision"));
                }
                else
                {
                    length = Convert.ToInt32(Configuration.GetConfiguration("geonetwork.property.default.length"));
                    precision = 0;
                }

                nodeShapefile.AddField(newFieldPair.Key, newFieldPair.Value, length, precision);
            }

            // 插入节点与节点的属性表
            for (int i = 0; i < ArcNumber; i++)
            {
                GeoNetworkArc oneArc = this.ArcList[i] as GeoNetworkArc;
                Polyline newPolyline = new Polyline();
                List<Point> pointList = new List<Point>();
                pointList.Add(new Point(oneArc.StartPoint.X, oneArc.StartPoint.Y));
                pointList.Add(new Point(oneArc.EndPoint.X, oneArc.EndPoint.Y));
                newPolyline.AddPart(pointList);
                nodeShapefile.AddFeature(newPolyline, oneArc.GetPropertySheet());
            }

            // 设置shapefile的坐标系统
            nodeShapefile.SetCoordinateRef(this.networkCoordinateSystem);

            return nodeShapefile;
        }

        public override Route SolvePath(int startNodeIndex, int endNodeIndex, string powerField)
        {
            GeoNetworkNode originNode = NodeList[startNodeIndex] as GeoNetworkNode;
            GeoNetworkNode destinationNode = NodeList[endNodeIndex] as GeoNetworkNode;

            double directDistance;
            if (this.networkCoordinateSystem.GetCoordinateType() == CoordinateType.Geographic)
            {
                directDistance = DistanceCalculator.SpatialDistanceGeo(originNode, destinationNode);
            }
            else
            {
                directDistance = DistanceCalculator.SpatialDistance(originNode, destinationNode);
            }

            if (powerField == null) powerField = "";

            // GeoNetwork里节点具备地理坐标后重写为A*算法
            if (neighborMatrix == null || networkChangeFlag == true || nowMatrixField != powerField)
            {
                RefreshNeighborMatrix(powerField);
            }

            Dictionary<int, int> parentDict = new Dictionary<int, int>();
            Dictionary<int, double> distanceDict = new Dictionary<int, double>();

            // 开放列表与封闭列表，开放列表中存储下面即将遍历的节点
            List<int> openList = new List<int>();
            List<int> closeList = new List<int>();

            openList.Add(startNodeIndex);
            distanceDict.Add(startNodeIndex, 0);
            parentDict.Add(startNodeIndex, -1);

            while (openList.Count > 0)
            {
                //List<double> FList = new List<double>();
                double minF = Double.MaxValue;
                int minFlistIndex = -1;

                for (int i = 0; i < openList.Count; i++)
                {
                    int nodeIndex = openList[i];

                    // 计算F值
                    int routeIndex = nodeIndex;
                    int parentIndex = parentDict[routeIndex];
                    double G = 0;
                    double H = 0;

                    if (parentIndex != -1)
                    {
                        G = distanceDict[nodeIndex];
                    }

                    GeoNetworkNode nowNode = NodeList[nodeIndex] as GeoNetworkNode;
                    GeoNetworkNode targetNode = NodeList[endNodeIndex] as GeoNetworkNode;

                    // 距离终点的直线距离
                    if (this.networkCoordinateSystem.GetCoordinateType() == CoordinateType.Geographic)
                    {
                        H = DistanceCalculator.SpatialDistanceGeo(nowNode.X, nowNode.Y, targetNode.X, targetNode.Y);
                    }
                    else
                    {
                        H = DistanceCalculator.SpatialDistance(nowNode.X, nowNode.Y, targetNode.X, targetNode.Y);
                    }

                    if (G + H < minF)
                    {
                        minF = G + H;
                        minFlistIndex = i;
                    }
                }

                // 选出F值最小的点
                int selectedNodeIndex = openList[minFlistIndex];
                openList.RemoveAt(minFlistIndex);

                // 将该节点的不在ClostList中的邻居加入OpenList
                List<LinkValuePair> links = this.neighborMatrix[selectedNodeIndex];
                foreach (LinkValuePair pair in links)
                {
                    if (closeList.Contains(pair.EndNodeIndex)) continue;

                    if (openList.Contains(pair.EndNodeIndex))
                    {
                        if (distanceDict[pair.EndNodeIndex] > distanceDict[selectedNodeIndex] + pair.Value)
                        {
                            parentDict[pair.EndNodeIndex] = selectedNodeIndex;
                            distanceDict[pair.EndNodeIndex] = distanceDict[selectedNodeIndex] + pair.Value;
                        }
                    }
                    else
                    {
                        if (distanceDict[selectedNodeIndex] + pair.Value < directDistance * 10)
                        {
                            distanceDict.Add(pair.EndNodeIndex, distanceDict[selectedNodeIndex] + pair.Value);
                            parentDict.Add(pair.EndNodeIndex, selectedNodeIndex);
                            openList.Add(pair.EndNodeIndex);
                        }
                    }
                }
                closeList.Add(selectedNodeIndex);

                // 终点加入OpenList后停止
                if (openList.Contains(endNodeIndex))
                {
                    break;
                }
            }

            if (openList.Count == 0)
            {
                return new Route(new List<INetworkNode>(), new List<int>(), 0);
            }
            else
            {
                List<INetworkNode> nodeList = new List<INetworkNode>();
                List<int> arcIndexList = new List<int>();

                int tempIndex = endNodeIndex;
                int parentIndex = parentDict[endNodeIndex];
                double distance = 0;

                while (parentIndex != -1)
                {
                    INetworkNode routeNode = NodeList[tempIndex];
                    LinkValuePair linkpair = this.neighborMatrix[parentIndex].Where(pair => pair.EndNodeIndex == tempIndex).ToList()[0];
                    arcIndexList.Insert(0, linkpair.ArcIndex);
                    distance += linkpair.Value;
                    nodeList.Insert(0, routeNode);
                    tempIndex = parentIndex;
                    parentIndex = parentDict[tempIndex];
                }

                nodeList.Insert(0, NodeList[tempIndex]);

                return new Route(nodeList, arcIndexList, distance);
            }
        }

        // Function: 基于节点间的距离关系产生预测性连接
        // Params:
        // maxTolerateDistance: 最大容忍距离，在maxTolerateDistance范围内的点产生连接
        // KLinks: 每个节点在其回合内最多连接K条边
        // judgeFunction: 节点属性的相似性判别函数，使用两个不同网络节点的属性表进行计算，判别方式为 !=0 构建实变，==0 构建虚边 
        public bool LinkNodes_KLink_MaxDistance(double maxTolerateDistance, int KLinks, Func<Dictionary<string, object>, Dictionary<string, object>, int> judgeFunction)
        {
            // 首先清除弧段容器中的全部弧段
            ArcList.Clear();

            this.neighborMatrix = new List<List<LinkValuePair>>();

            bool[] flagList = new bool[NodeNumber];

            for (int i = 0; i < NodeNumber; i++)
            {
                neighborMatrix.Add(new List<LinkValuePair>());
                flagList[i] = false;
            }

            for (int i = 0; i < NodeNumber; i++)
            {
                // 选一个未被处理过的节点开始尝试连接
                if (flagList[i] == true) continue;
                Queue<int> generateTree = new Queue<int>();
                generateTree.Enqueue(i);
                flagList[i] = true;

                while (generateTree.Count > 0)
                {
                    int tempNodeIndex = generateTree.Dequeue();
                    GeoNetworkNode tempNode = NodeList[tempNodeIndex] as GeoNetworkNode;
                    flagList[tempNodeIndex] = true;

                    List<KeyValuePair<int, double>> distanceList = new List<KeyValuePair<int, double>>();
                    // 计算剩余节点至该节点的长度
                    for (int j = 0; j < NodeNumber; j++)
                    {
                        if (flagList[j] == true)
                        {
                            continue;
                        }

                        GeoNetworkNode neighborNode = NodeList[j] as GeoNetworkNode;
                        if (networkCoordinateSystem.GetCoordinateType() == CoordinateType.Geographic)
                        {
                            double distance = DistanceCalculator.SpatialDistanceGeo(tempNode.X, tempNode.Y, neighborNode.X, neighborNode.Y);
                            distanceList.Add(new KeyValuePair<int, double>(j, distance));
                        }
                        else
                        {
                            double distance = DistanceCalculator.SpatialDistance(tempNode.X, tempNode.Y, neighborNode.X, neighborNode.Y);
                            distanceList.Add(new KeyValuePair<int, double>(j, distance));
                        }
                    }

                    // distanceList按长度升序排序
                    distanceList.Sort((item1, item2) =>
                    {
                        return item1.Value.CompareTo(item2.Value);
                    });

                    // 选取前K个，若不足K个则全取
                    for (int k = 0; k < Math.Min(KLinks, distanceList.Count); k++)
                    {
                        KeyValuePair<int, double> onePair = distanceList[k];
                        int endNodeIndex = onePair.Key;
                        double distance = onePair.Value;

                        // 只要当前超过，后面的都超了，直接结束
                        if (distance > maxTolerateDistance) break;

                        GeoNetworkNode neighborNode = NodeList[endNodeIndex] as GeoNetworkNode;

                        List<LinkValuePair> existingLinks = this.neighborMatrix[tempNodeIndex];

                        // 如果连接已经存在则跳过
                        if (existingLinks.Where(item => item.EndNodeIndex == endNodeIndex).Count() != 0) continue;

                        // 否则开始构建新边
                        int similarity = judgeFunction(tempNode.GetPropertySheet(), NodeList[endNodeIndex].GetPropertySheet());
                        Dictionary<string, object> arcData = new Dictionary<string, object>();

                        if (similarity == 0)
                        {
                            arcData.Add("LinkType", 0);
                        }
                        else
                        {
                            arcData.Add("LinkType", 1);
                        }

                        NetworkArc newArc = new NetworkArc(tempNode.GetID(), neighborNode.GetID(), arcData);
                        ArcList.Add(newArc);

                        // 顺便把邻接矩阵刷新一下
                        this.neighborMatrix[tempNodeIndex].Add(new LinkValuePair(endNodeIndex, distance, ArcList.Count - 1));
                        this.neighborMatrix[endNodeIndex].Add(new LinkValuePair(tempNodeIndex, distance, ArcList.Count - 1));

                        // 把新增的点加入generateTree
                        generateTree.Enqueue(endNodeIndex);
                    }
                }
            }

            return true;
        }

        public GeoNetworkArc GetGeoNetworkArc(int index)
        {
            if (index < -this.ArcNumber || index >= this.ArcNumber) throw new Exception("索引超出界限！");

            if (index < 0) index += this.ArcNumber;

            return this.ArcList[index] as GeoNetworkArc;
        }

        public GeoNetworkNode GetGeoNetworkNode(int index)
        {
            if (index < -this.NodeNumber || index >= this.NodeNumber) throw new Exception("索引超出界限！");

            if (index < 0) index += this.NodeNumber;

            return this.NodeList[index] as GeoNetworkNode;
        }

        public GeoNetworkNode GetGeoNetworkNodeByID(int ID)
        {
            IEnumerable<INetworkNode> nodeList = this.NodeList.Where(item => item.GetID() == ID);

            if (nodeList.Count() == 0) return null;

            return nodeList.ElementAt(0) as GeoNetworkNode;
        }

        public CoordinateBase GetGeoNetworkCoordinate()
        {
            return this.networkCoordinateSystem;
        }

        public int GetGeoNetworkNodeIndex(int ID)
        {
            IEnumerable<INetworkNode> nodeList = this.NodeList.Where(item => item.GetID() == ID);
            if (nodeList.Count() == 0) return -1;
            return this.NodeList.IndexOf(nodeList.ElementAt(0));
        }
    }
}
